/**
 *       Copyright (c) 2012 Lukas Zaruba
 *
 *   This file is part of Robot Playground.
 *
 *   Robot Playground is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   Robot Playground is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public License
 *   along with Robot Playground. If not, see <http://www.gnu.org/licenses/>.
 */
package net.zarubsys.robotplayground.core.log4j;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import net.zarubsys.robotplayground.core.Environment;

import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.MDC;
import org.apache.log4j.spi.LoggingEvent;

/**
 * DistributingFileAppender
 *
 * @author Lukas Zaruba, lukas.zaruba@gmail.com
 */
public class DistributingFileAppender extends AppenderSkeleton {
	
	private static final Logger LOG = Logger.getLogger(DistributingFileAppender.class);
	
	private final Map<String, FileAppender> appenders = new HashMap<String, FileAppender>();
	
	public DistributingFileAppender() {
		
	}

	@Override
	public void close() {
		if (closed) return;
	    closed = true;
		for (FileAppender appender : appenders.values()) {
			appender.close();
		}
	}

	@Override
	public boolean requiresLayout() {
		return true;
	}

	@Override
	protected void append(LoggingEvent event) {
		if (!checkEntryConditions()) return;
		Object rawLogPath = MDC.get(Environment.LOG_PATH_KEX);
		if (rawLogPath == null) {
			LOG.error("Recieved append from thread which doesn't have " + Environment.LOG_PATH_KEX + " set in its MDC!");
			return;
		}
		if (!(rawLogPath instanceof String)) {
			LOG.error("Recieved append from thread which has in its MDC property " + Environment.LOG_PATH_KEX + " something else than string! (" + rawLogPath + ")");
			return;
		}
		String logPath = (String) rawLogPath;
		FileAppender underlyingAppender = appenders.get(logPath);
		if (underlyingAppender == null) {
			try {
				underlyingAppender = new FileAppender(layout, logPath);
			} catch (IOException e) {
				LOG.error("Error while instantiating new FileAppender for path " + logPath + "!", e);
				return;
			}
			appenders.put(logPath, underlyingAppender);
		}
		underlyingAppender.append(event);
	}

	private boolean checkEntryConditions() {
		if (this.closed) {
			LOG.warn("Not allowed to write to a closed appender.");
			return false;
		}

		if (this.layout == null) {
			errorHandler.error("No layout set for the appender named [" + name + "].");
			return false;
		}
		return true;
	}

}

